package com.tianyadu.mmall.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器，拦截器会拦截所有请求
 *
 * @author xueyj
 * @date 2019-09-21 16:07
 */
@Slf4j
@Component
public class TimeInterceptor implements HandlerInterceptor {

    /**
     * 前置过滤器，在业务处理器处理请求之前被调用
     *
     * @param request  http请求
     * @param response http响应
     * @param handler  应用请求
     * @return boolean
     * @author xueyj
     * @date 2019/9/21-16:11
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            log.info("preHandle过滤器被执行了");
            log.info("被过滤类名，【{}】，被过滤方法，【{}】",
                    method.getBean().getClass().getName(),
                    method.getMethod().getName());
        }
        request.setAttribute("startTime", System.currentTimeMillis());
        return true;
    }

    /**
     * 后置过滤器,在业务处理器处理请求完成之后，生成视图之前执行，异常情况，不会触发该过滤器
     *
     * @param request      http请求
     * @param response     http响应
     * @param handler      应用请求
     * @param modelAndView 视图
     * @author xueyj
     * @date 2019/9/21-16:13
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info("postHandle过滤器被执行了");
        Long start = (Long) request.getAttribute("startTime");
        log.info("time interceptor 耗时:【{}】", (System.currentTimeMillis() - start));
    }

    /**
     * 在DispatcherServlet完全处理完请求之后被调用，可用于清理资源，
     * 不论正常返回或异常返回，都会执行该过滤器
     * 若正常返回，异常信息为空，否则异常信息不为空
     * <p>
     * 注：若自定义异常，经自定义异常处理器处理后，此代码块获取异常信息为空;
     * 因自定义控制器中异常信息处理优先于此代码块，故在此场景下，该代码块获取异常信息为空,
     * 若业务中所抛出的异常未经自定义异常处理器处理，即使用spring默认异常处理机制，则此代码块还是会获取到异常信息
     *
     * @param request  http请求
     * @param response http响应
     * @param handler  应用请求
     * @param ex       异常
     * @author xueyj
     * @date 2019/9/21-16:14
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        log.info("afterCompletion过滤器被执行了");
        Long start = (Long) request.getAttribute("startTime");
        log.info("time interceptor 耗时:【{}】", (System.currentTimeMillis() - start));
        log.info("异常信息，【{}】", ex);
    }
}